package com.likeycy.my.sort.cmp;

import com.likeycy.my.sort.CountingSort;
import com.likeycy.my.sort.RadixSort;

import java.text.DecimalFormat;

/**
 * @ClassName: Sort
 * @Description: 排序公共父类
 * @Author: sodagreen
 * @Date: 2021/3/27 6:33
 * @Version: 1.0
 */
public abstract class Sort<T extends Comparable<T>> implements Comparable<Sort<T>> {

    protected T[] array;
    /**
     * 比较总次数
     */
    private int cmpCount;
    /**
     * 交换总次数
     */
    private int swapCount;

    private long time;
    private DecimalFormat fmt = new DecimalFormat("#.00");

    public void sort(T[] array) {
        int flag = 2;
        if (array == null || array.length < flag) {
            return;
        }
        this.array = array;

        long begin = System.currentTimeMillis();
        sort();
        time = System.currentTimeMillis() - begin;
    }

    @Override
    public int compareTo(Sort<T> o) {
        int result = (int)(time - o.time);
        if (result != 0) {
            return result;
        }

        result = cmpCount - o.cmpCount;
        if (result != 0) {
            return result;
        }

        return swapCount - o.swapCount;
    }

    /**
     * 排序方法
     */
    protected abstract void sort();

    /**
     * <p> 比较指定的元素大小，返回大小结果 </p>
     * <p> 返回值小于 0，代表 array[i1] < array[i2] </p>
     * <p> 返回值等于 0，代表 array[i1] == array[i2] </p>
     * <p> 返回值大于 0，代表 array[i1] > array[i2] </p>
     *
     * @param i1 指定的第一个元素索引
     * @param i2 指定的第二个元素索引
     * @return 返回 int 比较结果
     */
    protected int cmp(int i1, int i2) {
        cmpCount++;
        return array[i1].compareTo(array[i2]);
    }

    /**
     * <p> 比较指定的元素大小，返回大小结果 </p>
     * <p> 返回值小于 0，代表 v1 < v2 </p>
     * <p> 返回值等于 0，代表 v1 == v2 </p>
     * <p> 返回值大于 0，代表 v1 > v2 </p>
     *
     * @param v1 指定的第一个元素值
     * @param v2 指定的第二个元素值
     * @return 返回 int 比较结果
     */
    protected int comparatorToElements(T v1, T v2) {
        cmpCount++;
        return v1.compareTo(v2);
    }

    /**
     * 交换
     *
     * @param i1 第一个索引
     * @param i2 第二个索引
     */
    protected void swap(int i1, int i2) {
        swapCount++;
        T temp = array[i1];
        array[i1] = array[i2];
        array[i2] = temp;
    }

    @Override
    public String toString() {
        String timeStr = "耗时：" + (time / 1000.0) + "s(" + time + "ms)";
        String compareCountStr = "比较：" + numberString(cmpCount);
        String swapCountStr = "交换：" + numberString(swapCount);
        String stableStr = "稳定性：" + isStable();
        return "【" + getClass().getSimpleName() + "】\n"
                + stableStr + " \t"
                + timeStr + " \t"
                + compareCountStr + "\t "
                + swapCountStr + "\n"
                + "------------------------------------------------------------------";
    }

    private String numberString(int number) {
        if (number < 10000) {
            return "" + number;
        }

        if (number < 100000000) {
            return fmt.format(number / 10000.0) + "万";
        }
        return fmt.format(number / 100000000.0) + "亿";
    }

    private boolean isStable() {
        if (this instanceof RadixSort) {
            return true;
        }
        if (this instanceof CountingSort) {
            return true;
        }
        if (this instanceof ShellSort) {
            return false;
        }
        if (this instanceof SelectionSort) {
            return false;
        }

        /*Student[] students = new Student[20];
        for (int i = 0; i < students.length; i++) {
            students[i] = new Student(i * 10, 10);
        }
        sort((T[]) students);
        for (int i = 1; i < students.length; i++) {
            int score = students[i].score;
            int prevScore = students[i - 1].score;
            if (score != prevScore + 10) {
                return false;
            }
        }*/
        return true;
    }
}
